package com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.ApiModelUtil;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.common.util.XWPFTUtil;
import com.xyht.sca_s.student_manage_system.modules.common.constant.FileSavePathConstant;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTips;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTipsRecord;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsMapper;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import com.xyht.sca_s.student_manage_system.modules.visitor.entity.dto.SmsUserDTO;
import com.xyht.sca_s.student_manage_system.modules.workApplication.entity.vo.SmsWorkApplicationDetailTorsionVO;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.entity.SmsWorkGroupApplication;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.entity.SmsWorkGroupApplicationDetail;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.entity.SmsWorkGroupApplicationProcess;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.entity.dto.*;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.entity.vo.*;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.mapper.SmsWorkGroupApplicationDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.mapper.SmsWorkGroupApplicationMapper;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.mapper.SmsWorkGroupApplicationMpjMapper;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.mapper.SmsWorkGroupApplicationProcessMapper;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.service.SmsWorkGroupApplicationService;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.agreement.constant.agreementObjectTypeConstant.AGREEMENT_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.examinePaymentEquipment.constant.isExportProcessConstant.EXPORT_PROCESS_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.examinePaymentEquipment.constant.paymentExamineStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.CopyTypeEnum.COPY_TYPE_ENUM_NONE;
import static com.xyht.sca_s.student_manage_system.modules.student.constant.StudentInfoCommonConstant.PER_SHEET_NUM;
import static com.xyht.sca_s.student_manage_system.modules.workApplication.constant.applicationObjectTypeConstant.WORK_APPLICATION_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.workApplication.constant.applicationObjectTypeConstant.WORK_APPLICATION_OBJECT_TYPE_ROLE;
import static com.xyht.sca_s.student_manage_system.modules.workApplication.constant.workApplicationStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.workApplication.constant.workApplicationTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.SortTypeConstant.SORT_TYPE_ALLOW_STATUS;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.SortTypeConstant.SORT_TYPE_TIME;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.applicationObjectTypeConstant.WORK_GROUP_APPLICATION_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.applicationObjectTypeConstant.WORK_GROUP_APPLICATION_OBJECT_TYPE_ROLE;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.isAnnexConstant.HAVE_ANNEX;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.workApplicationStatusConstant.WORK_STATUS_FORCED_FINISH;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.workApplicationStatusConstant.WORK_STATUS_FORCED_REJECT;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-06-12
 */
@Service
public class SmsWorkGroupApplicationServiceImpl extends ServiceImpl<SmsWorkGroupApplicationMapper, SmsWorkGroupApplication> implements SmsWorkGroupApplicationService {
    @Resource
    private FileSavePathConstant fileSavePathConstant;

    @Autowired
    private SmsWorkGroupApplicationMapper smsWorkGroupApplicationMapper;

    @Autowired
    private SmsWorkGroupApplicationProcessMapper smsWorkGroupApplicationProcessMapper;

    @Autowired
    private SmsWorkGroupApplicationDetailMapper smsWorkGroupApplicationDetailMapper;

    @Autowired
    private NewTipsUtil newTipsUtil;

    @Autowired
    private CacheUtil cacheUtil;

    @Autowired
    private SmsWorkGroupApplicationMpjMapper smsWorkGroupApplicationMpjMapper;

    @Autowired
    private SmsUserMapper smsUserMapper;

    @Autowired
    private ApiModelUtil apiModelUtil;

    @Autowired
    private SmsRoleMapper smsRoleMapper;
    @Resource
    private SmsNewTipsMapper smsNewTipsMapper;
    @Resource
    private SmsNewTipsRecordMapper smsNewTipsRecordMapper;
    @Transactional
    @Override
    public ResponseResult smsWorkGroupApplicationAdd(SmsWorkGroupApplicationVO smsWorkGroupApplicationVO, String user_id) {
        List<SmsWorkGroupApplicationProcess> fillProcessList =
                smsWorkGroupApplicationProcessMapper.selectList(new QueryWrapper<SmsWorkGroupApplicationProcess>()
                        .lambda()
                        .eq(SmsWorkGroupApplicationProcess::getProcessIsApplicationEdit, true)
                        .eq(SmsWorkGroupApplicationProcess::getProcessIsUse, true)
                        .orderByAsc(SmsWorkGroupApplicationProcess::getProcessSort));
        if (fillProcessList != null && fillProcessList.size() > 0) {
            if (smsWorkGroupApplicationVO.getProcessList() == null || smsWorkGroupApplicationVO.getProcessList().size() < 1) {
                return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_ALLOW_USER_NOT_SETTING);
            }
            //判断申请人是否将全部需要编辑流程填写
            List<SmsWorkGroupApplicationProcess> filterList = fillProcessList
                    .stream()
                    .filter(process -> {
                                List<String> result = smsWorkGroupApplicationVO.getProcessList()
                                        .stream()
                                        .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                                        .map(SmsWorkGroupApplicationDetailVO::getId)
                                        .collect(Collectors.toList());
                                //匹配的去除  未匹配的留下
                                if (result.size() > 0) {
                                    return false;
                                } else {
                                    return true;
                                }
                            }
                    )
                    .collect(Collectors.toList());
            if (filterList.size() > 0) {
                return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_ALLOW_PROCESS_NOT_FILL);
            }
        }

        //创建申请表
        SmsWorkGroupApplication addWorkApplication = new SmsWorkGroupApplication();
        BeanUtils.copyProperties(smsWorkGroupApplicationVO, addWorkApplication);
        addWorkApplication.setApplicationApplyUserId(user_id);
        addWorkApplication.setAllowStatus(WORK_STATUS_WAIT_ALLOW);
        smsWorkGroupApplicationMapper.insert(addWorkApplication);

        if (addWorkApplication.getId() == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        String application_id = addWorkApplication.getId();

        //创建审批流程
        List<SmsWorkGroupApplicationProcess> originProcessList =
                smsWorkGroupApplicationProcessMapper.selectList(new QueryWrapper<SmsWorkGroupApplicationProcess>()
                        .lambda()
                        .eq(SmsWorkGroupApplicationProcess::getProcessIsUse, true)
                        .orderByAsc(SmsWorkGroupApplicationProcess::getProcessSort));
        if (originProcessList == null || originProcessList.size() < 1) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_PROCESS_NOT_SETTING));
        }
        int sort = 1;
        for (SmsWorkGroupApplicationProcess process : originProcessList) {
            //判断管理员是否配置初始流程
            if (!process.getProcessIsApplicationEdit()) {
                if (isNullOrEmpty(process.getProcessObjectId()) || isNullOrEmpty(process.getProcessObjectType())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_PROCESS_NOT_SETTING));
                }
            }

            if(!smsWorkGroupApplicationVO.getIsOpenHouQin()){
                if(process.getProcessName().equals("后勤处领导")){
                    continue;
                }
            }
            SmsWorkGroupApplicationDetail addDetail =
                    new SmsWorkGroupApplicationDetail();

            addDetail.setApplicationId(application_id);
            addDetail.setProcessId(process.getId());
            addDetail.setProcessIsSign(process.getProcessIsSign());
            addDetail.setProcessIsStamp(process.getProcessIsStamp());
            addDetail.setProcessName(process.getProcessName());
            addDetail.setDetailAllowStatus(WORK_STATUS_WAIT_ALLOW);

            //申请人可编辑流程
            if (process.getProcessIsApplicationEdit()) {
                List<SmsWorkGroupApplicationDetailVO> filterList = smsWorkGroupApplicationVO.getProcessList()
                        .stream()
                        .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                        .collect(Collectors.toList());
                if (filterList.size() < 1) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_PROCESS_NOT_FILL));
                }
                SmsWorkGroupApplicationDetailVO fillProcessReq = filterList.get(0);

                if (isNullOrEmpty(fillProcessReq.getProcessObjectId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
                }
                //判断是否开启此节点
                Boolean isOpenDetail = fillProcessReq.getIsOpenDetail();
                if(!isOpenDetail){
                    continue;
                }
                addDetail.setProcessIsSign(fillProcessReq.getProcessIsSign());
                addDetail.setProcessIsStamp(fillProcessReq.getProcessIsStamp());
                addDetail.setDetailSort(sort++);
                addDetail.setProcessObjectId(fillProcessReq.getProcessObjectId());
                addDetail.setProcessObjectType(WORK_GROUP_APPLICATION_OBJECT_TYPE_PERSON);
            } else {
                addDetail.setDetailSort(sort++);
                addDetail.setProcessObjectId(process.getProcessObjectId());
                addDetail.setProcessObjectType(process.getProcessObjectType());
            }
            smsWorkGroupApplicationDetailMapper.insert(addDetail);
        }

        //消息通知
        //通知流程第一个节点
        SmsWorkGroupApplicationDetail firstDetail =
                smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                        .lambda()
                        .eq(SmsWorkGroupApplicationDetail::getApplicationId, application_id)
                        .eq(SmsWorkGroupApplicationDetail::getDetailSort, 1)
                        .orderByAsc(SmsWorkGroupApplicationDetail::getDetailSort));
        RangeTypeEnum rangeTypeEnum;
        if (firstDetail.getProcessIsApplicationEdit().equals(1)) {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
        } else {
            if (firstDetail.getProcessObjectType() == WORK_APPLICATION_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
        }

        List<String> rangeList = new ArrayList<>();
        rangeList.add(firstDetail.getProcessObjectId());

        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                user_id,
                rangeTypeEnum,
                rangeList,
                COPY_TYPE_ENUM_NONE,
                null,
                AppTypeEnum.APP_TYPE_ENUM_WORK_GROUP_APPLICATION,
                application_id,
                null,
                null,
                firstDetail.getId(),
                null,
                null,
                null,
                smsWorkGroupApplicationVO.getMessageTitle());
        return CommonResult.success();
    }

    @Override
    public ResponseResult smsWorkGroupApplicationUpdate(SmsWorkGroupApplicationVO smsWorkGroupApplicationVO, String user_id) {
        //查看审批表是否存在且是否为本人
        SmsWorkGroupApplication paymentExamine =
                smsWorkGroupApplicationMapper.selectOne(new QueryWrapper<SmsWorkGroupApplication>()
                        .lambda()
                        .eq(SmsWorkGroupApplication::getId, smsWorkGroupApplicationVO.getApplyId())
                        .eq(SmsWorkGroupApplication::getApplicationApplyUserId, user_id));
        if (paymentExamine == null || isNullOrEmpty(paymentExamine.getId())) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_EXIST);
        }
        if (paymentExamine.getAllowStatus() != WORK_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_CANCEL_FAIL_ALLOWED);
        }
        //修改校验审批节点未审批
        List<SmsWorkGroupApplicationDetail> detailList = smsWorkGroupApplicationDetailMapper.selectList(new LambdaQueryWrapper<SmsWorkGroupApplicationDetail>()
                .eq(SmsWorkGroupApplicationDetail::getApplicationId, smsWorkGroupApplicationVO.getApplyId())
                .eq(SmsWorkGroupApplicationDetail::getDetailSort,1));
        if (detailList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_PROCESS_NOT_EXIST);
        }
        SmsWorkGroupApplicationDetail smsWorkGroupApplicationDetail = detailList.get(0);
        if (smsWorkGroupApplicationDetail.getDetailAllowStatus() != WORK_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_UPDATE_FAIL_ALLOWED);
        }
        //修改申请表
        BeanUtils.copyProperties(smsWorkGroupApplicationVO, paymentExamine);
        smsWorkGroupApplicationMapper.updateById(paymentExamine);

        return CommonResult.success();
    }

    @Transactional
    @Override
    public ResponseResult smsWorkGroupApplicationCancel(SmsWorkGroupApplicationCancelVO smsWorkGroupApplicationCancelVO, String user_id) {
        if (isNullOrEmpty(smsWorkGroupApplicationCancelVO.getApplicationId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //查看审批表是否存在且是否为本人
        SmsWorkGroupApplication paymentExamine =
                smsWorkGroupApplicationMapper.selectOne(new QueryWrapper<SmsWorkGroupApplication>()
                        .lambda()
                        .eq(SmsWorkGroupApplication::getId, smsWorkGroupApplicationCancelVO.getApplicationId())
                        .eq(SmsWorkGroupApplication::getApplicationApplyUserId, user_id));
        if (paymentExamine == null || isNullOrEmpty(paymentExamine.getId())) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_EXIST);
        }
        if (paymentExamine.getAllowStatus() != WORK_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_CANCEL_FAIL_ALLOWED);
        }

        //判断是否审批中
//        List<SmsWorkGroupApplicationDetail> detailList =
//                smsWorkGroupApplicationDetailMapper.selectList(new QueryWrapper<SmsWorkGroupApplicationDetail>()
//                        .lambda()
//                        .eq(SmsWorkGroupApplicationDetail::getApplicationId, smsWorkGroupApplicationCancelVO.getApplicationId())
//                        .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_PASS));
//        if (detailList != null && detailList.size() > 0) {
//            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_CANCEL_FAIL_ALLOWING);
//        }

        //撤回审批
        SmsWorkGroupApplication cancelExamine = new SmsWorkGroupApplication();
        cancelExamine.setId(smsWorkGroupApplicationCancelVO.getApplicationId());
        cancelExamine.setAllowStatus(WORK_STATUS_CANCEL);
        cancelExamine.setEndTime(new Date());
        smsWorkGroupApplicationMapper.updateById(cancelExamine);

        //修改节点状态
        SmsWorkGroupApplicationDetail cancelExamineDetail = new SmsWorkGroupApplicationDetail();
        cancelExamineDetail.setDetailAllowStatus(WORK_STATUS_CANCEL);

        smsWorkGroupApplicationDetailMapper.update(cancelExamineDetail, new QueryWrapper<SmsWorkGroupApplicationDetail>()
                .lambda()
                .eq(SmsWorkGroupApplicationDetail::getApplicationId, smsWorkGroupApplicationCancelVO.getApplicationId())
                .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus,WORK_STATUS_WAIT_ALLOW));

        //消息通知
        newTipsUtil.cancelFinishTips(smsWorkGroupApplicationCancelVO.getApplicationId());

        return CommonResult.success();
    }

    @Transactional
    @Override
    public ResponseResult allowSmsWorkApplication(SmsWorkGroupApplicationAllowVO allowVO, String user_id) {
        if (isNullOrEmpty(allowVO.getApplication_id()) || isNullOrEmpty(allowVO.getDetail_id())
                || isNullOrEmpty(allowVO.getDetailAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (allowVO.getDetailAllowStatus() != WORK_STATUS_PASS
                && allowVO.getDetailAllowStatus() != WORK_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWorkGroupApplicationDetail applicationDetail =
                smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                        .lambda()
                        .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id())
                        .eq(SmsWorkGroupApplicationDetail::getId, allowVO.getDetail_id())
                        .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_WAIT_ALLOW));
        if (isNullOrEmpty(applicationDetail)) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_ALLOW_FAIL);
        }

        //判断该节点是否本人审批（防止调节点审批）
        if (applicationDetail.getProcessObjectType() == WORK_APPLICATION_OBJECT_TYPE_PERSON) {
            if (!applicationDetail.getProcessObjectId().equals(user_id)) {
                return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_ALLOW_FAIL);
            }
        } else {
            List<String> roleList = cacheUtil.getRoleList(user_id);
            List<String> filterRoleList = roleList.stream().filter(role -> role.equals(applicationDetail.getProcessObjectId())).collect(Collectors.toList());
            if (filterRoleList.size() < 1) {
                return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_ALLOW_FAIL);
            }
        }
        if (!applicationDetail.getDetailSort().equals(1)) {
            SmsWorkGroupApplicationDetail preDetail =
                    smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                            .lambda()
                            .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id())
                            .eq(SmsWorkGroupApplicationDetail::getDetailSort, applicationDetail.getDetailSort() - 1));
            if (preDetail != null && !isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getDetailAllowStatus() != WORK_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_ALLOW_FAIL);
                }
            }
        }


        SmsWorkGroupApplicationDetail allowDetail = new SmsWorkGroupApplicationDetail();
        allowDetail.setId(allowVO.getDetail_id());
        allowDetail.setDetailAllowStatus(allowVO.getDetailAllowStatus());
        if (!isNullOrEmpty(allowVO.getDetailAllowOpinion())) {
            allowDetail.setDetailAllowOption(allowVO.getDetailAllowOpinion());
        }
        Date nowDate = new Date();
        allowDetail.setDetailAllowTime(nowDate);
        allowDetail.setDetailAllowUserId(user_id);

        if (applicationDetail.getProcessIsSign()) {
            if (isNullOrEmpty(allowVO.getDetailAllowSign())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            allowDetail.setDetailAllowSign(allowVO.getDetailAllowSign());
        }
        if (applicationDetail.getProcessIsStamp()) {
            if (isNullOrEmpty(allowVO.getDetailAllowStamp())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            allowDetail.setDetailAllowStamp(allowVO.getDetailAllowStamp());
        }
        smsWorkGroupApplicationDetailMapper.updateById(allowDetail);

        boolean is_done = false;

        //判断是否最后一个节点 是否驳回
        Integer detailCount = smsWorkGroupApplicationDetailMapper.selectCount(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                .lambda()
                .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id()));
        if (detailCount.equals(applicationDetail.getDetailSort()) || allowVO.getDetailAllowStatus() == WORK_STATUS_DENY) {
            is_done = true;

            SmsWorkGroupApplication updateApplication = new SmsWorkGroupApplication();
            updateApplication.setId(allowVO.getApplication_id());
            updateApplication.setEndTime(nowDate);
            updateApplication.setAllowStatus(allowVO.getDetailAllowStatus());
            smsWorkGroupApplicationMapper.updateById(updateApplication);
        }

        //节点驳回 重置其余节点状态
        if (allowVO.getDetailAllowStatus() == WORK_STATUS_DENY) {
            SmsWorkGroupApplicationDetail updateDenyDetail =
                    new SmsWorkGroupApplicationDetail();
            updateDenyDetail.setDetailAllowStatus(WORK_STATUS_DENY_FINISH);
            smsWorkGroupApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsWorkGroupApplicationDetail>()
                    .lambda()
                    .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id())
                    .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_WAIT_ALLOW));
        }


        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (allowVO.getDetailAllowStatus() == WORK_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(allowVO.getApplication_id(), user_id, result_status);
        } else {
            SmsWorkGroupApplicationDetail nextDetail =
                    smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                            .lambda()
                            .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id())
                            .eq(SmsWorkGroupApplicationDetail::getDetailSort, applicationDetail.getDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum;
            if (nextDetail.getProcessIsApplicationEdit().equals(1)) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                if (nextDetail.getProcessObjectType() == WORK_APPLICATION_OBJECT_TYPE_ROLE) {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
                } else {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                }
            }

            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(allowVO.getApplication_id(),
                    user_id,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult getSmsWorkGroupApplicationList(String search_str, Integer allowStatus, String user_id, Integer application_type, Integer sort, Integer pageNum, Integer pageSize) {
        if (isNullOrEmpty(application_type)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsWorkGroupApplicationDTO> respList = new ArrayList<>();
        int total = 0;
        if (application_type == WORK_TYPE_APPLY) {
            Page<SmsWorkGroupApplication> page = new Page<>(pageNum, pageSize);
            QueryWrapper<SmsWorkGroupApplication> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(SmsWorkGroupApplication::getApplicationApplyUserId, user_id);

            //排序方式 0:审批时间 1:审批状态
            if (!isNullOrEmpty(sort)) {
                if (sort == SORT_TYPE_TIME) {
                    queryWrapper.lambda().orderByDesc(SmsWorkGroupApplication::getCreateTime);
                } else if (sort == SORT_TYPE_ALLOW_STATUS) {
                    queryWrapper.lambda()
                            .orderByAsc(SmsWorkGroupApplication::getAllowStatus)
                            .orderByDesc(SmsWorkGroupApplication::getCreateTime);
                }
            }

            if(!isNullOrEmpty(search_str)){
                queryWrapper.lambda().and(q ->{
                   q.like(SmsWorkGroupApplication::getRequestingUnit,search_str)
                   .or()
                   .like(SmsWorkGroupApplication::getAgent,search_str)
                   .or()
                   .like(SmsWorkGroupApplication::getMatter,search_str);
                });
            }

            if(!isNullOrEmpty(allowStatus)){
                queryWrapper.lambda().eq(SmsWorkGroupApplication::getAllowStatus,allowStatus);
            }
            smsWorkGroupApplicationMapper.selectPage(page, queryWrapper);
            respList = page.getRecords()
                    .stream()
                    .map(smsWorkGroupApplication -> {
                        SmsWorkGroupApplicationDTO smsWorkGroupApplicationDTO =
                                new SmsWorkGroupApplicationDTO();
                        BeanUtils.copyProperties(smsWorkGroupApplication, smsWorkGroupApplicationDTO);
                        smsWorkGroupApplicationDTO.setApplicationId(smsWorkGroupApplication.getId());

                        SmsUser smsUser = cacheUtil.getUserInfo(smsWorkGroupApplication.getApplicationApplyUserId());
                        SmsWorkGroupApplicationUserDTO smsWorkApplicationUserDTO = new SmsWorkGroupApplicationUserDTO();
                        if (smsUser != null) {
                            BeanUtils.copyProperties(smsUser, smsWorkApplicationUserDTO);
                        }
                        smsWorkGroupApplicationDTO.setApplyUserInfo(smsWorkApplicationUserDTO);
                        return smsWorkGroupApplicationDTO;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (application_type == WORK_TYPE_ALLOWED) {
            Page<SmsWorkGroupApplicationMpjDTO> page = new Page<>(pageNum, pageSize);
            MPJLambdaWrapper<SmsWorkGroupApplicationDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
            mpjLambdaWrapper.selectAll(SmsWorkGroupApplicationDetail.class)
                    .selectAll(SmsWorkGroupApplication.class)
                    .selectAs(SmsWorkGroupApplication::getCreateTime, "createTime")
                    .selectAs(SmsWorkGroupApplicationDetail::getId, "detailId")
                    .leftJoin(SmsWorkGroupApplication.class, SmsWorkGroupApplication::getId, SmsWorkGroupApplicationDetail::getApplicationId)
                    .eq(SmsWorkGroupApplicationDetail::getDetailAllowUserId, user_id)
                   // .orderByDesc(SmsWorkGroupApplication::getCreateTime)
                    .orderByDesc(SmsWorkGroupApplicationDetail::getDetailAllowTime)
            ;

            mpjLambdaWrapper.and(wrapper -> {
                wrapper.eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_PASS)
                        .or()
                        .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_DENY);
            });
            if(!isNullOrEmpty(search_str)){
                List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                        .lambda()
                        .like(SmsUser::getRealName, search_str))
                        .stream()
                        .map(SmsUser::getId).collect(Collectors.toList());

                mpjLambdaWrapper.and(queryWrapper ->{
                    queryWrapper.like(SmsWorkGroupApplication::getMatter,search_str)
                            .or()
                            .like(SmsWorkGroupApplication::getAgent,search_str)
                            .or()
                            .like(SmsWorkGroupApplication::getRequestingUnit,search_str);
                    if(userIds.size() > 0) {
                        queryWrapper.or().in(SmsWorkGroupApplication::getApplicationApplyUserId, userIds);
                    }
                });
            }
            smsWorkGroupApplicationMpjMapper.selectJoinPage(page, SmsWorkGroupApplicationMpjDTO.class, mpjLambdaWrapper);

            respList = page.getRecords()
                    .stream()
                    .map(smsExamineMPJResp -> {
                        SmsWorkGroupApplicationDTO smsWorkApplicationDTO = new SmsWorkGroupApplicationDTO();
                        BeanUtils.copyProperties(smsExamineMPJResp, smsWorkApplicationDTO);
                        smsWorkApplicationDTO.setCreateTime(smsExamineMPJResp.getCreateTime());
                        smsWorkApplicationDTO.setAllowStatus(smsExamineMPJResp.getDetailAllowStatus());

                        SmsUser applyUser = cacheUtil.getUserInfo(smsWorkApplicationDTO.getApplicationApplyUserId());
                        SmsWorkGroupApplicationUserDTO smsWorkApplicationUserDTO = new SmsWorkGroupApplicationUserDTO();
                        if (applyUser != null) {
                            BeanUtils.copyProperties(applyUser, smsWorkApplicationUserDTO);
                        }
                        smsWorkApplicationDTO.setApplyUserInfo(smsWorkApplicationUserDTO);

                        SmsUser allowUser = cacheUtil.getUserInfo(smsWorkApplicationDTO.getDetailAllowUserId());
                        SmsWorkGroupApplicationUserDTO smsApplicationAllowUserResp = new SmsWorkGroupApplicationUserDTO();
                        if (allowUser != null) {
                            BeanUtils.copyProperties(allowUser, smsApplicationAllowUserResp);
                        }
                        smsWorkApplicationDTO.setAllowUserInfo(smsApplicationAllowUserResp);

                        return smsWorkApplicationDTO;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (application_type == WORK_TYPE_ALLOW_WAIT_ME) {
            List<String> roleList = cacheUtil.getRoleList(user_id);

            //获取所有待审批申请流程节点
            List<SmsWorkGroupApplicationDetail> allDetailList =
                    smsWorkGroupApplicationDetailMapper.selectList(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                            .lambda()
                            .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_WAIT_ALLOW));

            List<SmsWorkGroupApplicationDetail> filterDetailList = allDetailList.stream()
                    .filter(detail -> {
                        if (detail.getProcessIsApplicationEdit().equals(1)) {
                            if (!detail.getProcessObjectId().equals(user_id)) {
                                return false;
                            }
                        } else {
                            if (detail.getProcessObjectType() == WORK_APPLICATION_OBJECT_TYPE_PERSON) {
                                if (!detail.getProcessObjectId().equals(user_id)) {
                                    return false;
                                }
                            } else {
                                List<String> filterRoleList = roleList.stream().filter(role -> role.equals(detail.getProcessObjectId())).collect(Collectors.toList());
                                if (filterRoleList.size() < 1) {
                                    return false;
                                }
                            }
                        }


                        if (detail.getDetailSort().equals(1)) {
                            return true;
                        }
                        //判断上一个流程节点是否完成
                        SmsWorkGroupApplicationDetail preDetail =
                                smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                                        .lambda()
                                        .eq(SmsWorkGroupApplicationDetail::getApplicationId, detail.getApplicationId())
                                        .eq(SmsWorkGroupApplicationDetail::getDetailSort, detail.getDetailSort() - 1)
                                        .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_PASS));
                        if (preDetail == null || isNullOrEmpty(preDetail.getId())) {
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());
            if (filterDetailList.size() > 0) {
                List<String> detailIDList = filterDetailList.stream().map(SmsWorkGroupApplicationDetail::getId).collect(Collectors.toList());

                Page<SmsWorkGroupApplicationMpjDTO> page = new Page<>(pageNum, pageSize);
                MPJLambdaWrapper<SmsWorkGroupApplicationDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
                mpjLambdaWrapper.selectAll(SmsWorkGroupApplicationDetail.class)
                        .selectAll(SmsWorkGroupApplication.class)
                        .selectAs(SmsWorkGroupApplication::getCreateTime, "createTime")
                        .selectAs(SmsWorkGroupApplicationDetail::getId, "detailId")
                        .leftJoin(SmsWorkGroupApplication.class, SmsWorkGroupApplication::getId, SmsWorkGroupApplicationDetail::getApplicationId)
                        .in(SmsWorkGroupApplicationDetail::getId, detailIDList)
                        .orderByDesc(SmsWorkGroupApplication::getCreateTime)
                        .orderByDesc(SmsWorkGroupApplicationDetail::getDetailAllowTime)
                ;
                if(!isNullOrEmpty(search_str)){
                    List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                            .lambda()
                            .like(SmsUser::getRealName, search_str))
                            .stream()
                            .map(SmsUser::getId).collect(Collectors.toList());

                    mpjLambdaWrapper.and(queryWrapper ->{
                        queryWrapper.like(SmsWorkGroupApplication::getMatter,search_str)
                                .or()
                                .like(SmsWorkGroupApplication::getRequestingUnit,search_str)
                                .or()
                                .like(SmsWorkGroupApplication::getAgent,search_str);
                        if(userIds.size() > 0) {
                            queryWrapper.or().in(SmsWorkGroupApplication::getApplicationApplyUserId, userIds);
                        }
                    });
                }
                smsWorkGroupApplicationMpjMapper.selectJoinPage(page, SmsWorkGroupApplicationMpjDTO.class, mpjLambdaWrapper);

                respList = page.getRecords()
                        .stream()
                        .map(smsExamineMPJResp -> {
                            SmsWorkGroupApplicationDTO smsExamineResp = new SmsWorkGroupApplicationDTO();
                            BeanUtils.copyProperties(smsExamineMPJResp, smsExamineResp);
                            smsExamineResp.setApplicationId(smsExamineMPJResp.getApplicationId());
                            smsExamineResp.setCreateTime(smsExamineMPJResp.getCreateTime());

                            SmsUser applyUser = cacheUtil.getUserInfo(smsExamineResp.getApplicationApplyUserId());
                            SmsWorkGroupApplicationUserDTO smsExamineUserResp = new SmsWorkGroupApplicationUserDTO();
                            if (applyUser != null) {
                                BeanUtils.copyProperties(applyUser, smsExamineUserResp);
                            }
                            smsExamineResp.setApplyUserInfo(smsExamineUserResp);

                            return smsExamineResp;
                        })
                        .collect(Collectors.toList());
                total = (int) page.getTotal();

            }
        }
        return CommonResult.success(respList, total);
    }

    @Override
    public ResponseResult getSmsWorkGroupApplicationDetail(String application_id, String user_id) {
        if (isNullOrEmpty(application_id)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsWorkGroupApplication workApplication = smsWorkGroupApplicationMapper.selectById(application_id);
        if (workApplication == null || isNullOrEmpty(workApplication.getId())) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_EXIST);
        }

        SmsWorkGroupApplicationDTO workApplicationDTO = new SmsWorkGroupApplicationDTO();
        BeanUtils.copyProperties(workApplication, workApplicationDTO);
        workApplicationDTO.setApplicationId(workApplication.getId());

        SmsUser smsUser = cacheUtil.getUserInfo(workApplicationDTO.getApplicationApplyUserId());
        SmsWorkGroupApplicationUserDTO smsWorkApplicationUserDTO = new SmsWorkGroupApplicationUserDTO();
        if (smsUser != null) {
            BeanUtils.copyProperties(smsUser, smsWorkApplicationUserDTO);
        }
        workApplicationDTO.setApplyUserInfo(smsWorkApplicationUserDTO);

        List<SmsWorkGroupApplicationDetailDTO> detailRespList =
                smsWorkGroupApplicationDetailMapper.selectList(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                        .lambda()
                        .eq(SmsWorkGroupApplicationDetail::getApplicationId, application_id)
                        .orderByAsc(SmsWorkGroupApplicationDetail::getDetailSort))
                        .stream()
                        .map(detail -> {
                            SmsWorkGroupApplicationDetailDTO detailResp = new SmsWorkGroupApplicationDetailDTO();
                            BeanUtils.copyProperties(detail, detailResp);
                            detailResp.setDetailAllowOption(detail.getDetailAllowOption());
                            detailResp.setProcessIsSign(detail.getProcessIsSign());
                            detailResp.setProcessIsStamp(detail.getProcessIsStamp());
                            if(detailResp.getProcessObjectType()==WORK_GROUP_APPLICATION_OBJECT_TYPE_PERSON){
                                SmsUser smsUser1 = smsUserMapper.selectById(detailResp.getProcessObjectId());
                                if(!isNullOrEmpty(smsUser1)) {
                                    detailResp.setRealName(smsUser1.getRealName());
                                    detailResp.setHeadPic(smsUser1.getUserPic());
                                }
                            }

                            else if(detailResp.getProcessObjectType()==WORK_GROUP_APPLICATION_OBJECT_TYPE_ROLE){
                                SmsRole smsRole = smsRoleMapper.selectById(detailResp.getProcessObjectId());
                                if(!isNullOrEmpty(smsRole)) {
                                    detailResp.setRealName(smsRole.getRoleName());
                                }
                            }
                            if (!isNullOrEmpty(detailResp.getDetailAllowUserId())) {
                                SmsUser userInfo = cacheUtil.getUserInfo(detailResp.getDetailAllowUserId());
                                SmsWorkGroupApplicationUserDTO applicationUserDTO = new SmsWorkGroupApplicationUserDTO();
                                if (userInfo != null) {
                                    BeanUtils.copyProperties(userInfo, applicationUserDTO);
                                }
                                detailResp.setAllowUserInfo(applicationUserDTO);
                            }
                            return detailResp;
                        })
                        .collect(Collectors.toList());
        workApplicationDTO.setDetailList(detailRespList);
        return CommonResult.success(workApplicationDTO);
    }

    @Override
    public ResponseResult getSmsWorkGroupApplicationOriginSettingProcess() {
        List<SmsWorkGroupApplicationOriginSettingProcessDTO> respList =
                smsWorkGroupApplicationProcessMapper.selectList(new QueryWrapper<SmsWorkGroupApplicationProcess>()
                        .lambda()
                        .eq(SmsWorkGroupApplicationProcess::getProcessIsApplicationEdit, true)
                        .eq(SmsWorkGroupApplicationProcess::getProcessIsUse,true)
                        .orderByAsc(SmsWorkGroupApplicationProcess::getProcessSort))
                        .stream()
                        .map(process -> {
                            SmsWorkGroupApplicationOriginSettingProcessDTO smsPaymentExamineOriginSettingProcessResp =
                                    new SmsWorkGroupApplicationOriginSettingProcessDTO();
                            BeanUtils.copyProperties(process, smsPaymentExamineOriginSettingProcessResp);
                            return smsPaymentExamineOriginSettingProcessResp;
                        })
                        .collect(Collectors.toList());
        return CommonResult.success(respList);
    }

    @Override
    public ResponseResult selectAgent(String person_name) {
        List<SmsUserDTO> list1 = new ArrayList<>();
        if (isNullOrEmpty(person_name)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        QueryWrapper<SmsUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SmsUser::getRealName, person_name);
        queryWrapper.lambda().eq(SmsUser::getFlag, 0);
        SmsUser smsUser = smsUserMapper.selectOne(queryWrapper);
        if (isNullOrEmpty(smsUser)) {
            return CommonResult.success(list1, 0);
        }
        List<SmsUser> list = smsUserMapper.selectList(queryWrapper);
        if (isNullOrEmpty(list) || list.size() == 0) {
            return CommonResult.success(list1, 0);
        }
        for (SmsUser smsUser1 : list) {
            SmsUserDTO smsUserDTO = new SmsUserDTO();
            BeanUtils.copyProperties(smsUser1, smsUserDTO);
            list1.add(smsUserDTO);
        }
        return CommonResult.success(list1);
    }

    @Autowired
    private XWPFTUtil xwpftUtil;

    @Override
    @Async
    public Future<ResponseResult> tableDownload(String apply_id, HttpServletResponse response) {
        SmsWorkGroupApplication smsWorkGroupApplication = smsWorkGroupApplicationMapper.selectById(apply_id);
        if (smsWorkGroupApplication == null || smsWorkGroupApplication.getId() == null) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_EXIST));
        }
//        if (smsWorkGroupApplication.getAllowStatus() == WORK_STATUS_WAIT_ALLOW) {
//            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_DOWNLOAD_FAIL));
//        }

        String OSName = System.getProperty("os.name");
        String filePath = OSName.toLowerCase().startsWith("win") ? fileSavePathConstant.getFILE_DOWNLOAD_PATH()
                : fileSavePathConstant.getFILE_DOWNLOAD_PATH_LINUX();

        String newFilePath = filePath + apply_id + ".docx";
        String pdfFilePath = filePath + apply_id + ".pdf";

        File pdfFile = new File(pdfFilePath);

      //  if (!pdfFile.exists()) {
            try {

                String isAnnex = "";
                if (smsWorkGroupApplication.getIsAnnex() != null && smsWorkGroupApplication.getIsAnnex() == HAVE_ANNEX) {
                    isAnnex = "有";
                } else {
                    isAnnex = "无";
                }
                String signTime = TimeUtil.DateHanZiSimpleFormat(smsWorkGroupApplication.getCreateTime());

                List<String> picTagList = new ArrayList<>();
                List<String> textTagList = new ArrayList<>();

                Map<String, Object> map = new HashMap<>();
                map.put("applyTime", signTime);
                map.put("requestingUnit", smsWorkGroupApplication.getRequestingUnit());
                map.put("agent", smsWorkGroupApplication.getAgent());
                map.put("isAnnex",isAnnex);
                map.put("matter", smsWorkGroupApplication.getMatter());
                map.put("budgetAmount", smsWorkGroupApplication.getBudgetAmount());
                map.put("contentAbstract", smsWorkGroupApplication.getContentAbstract());
                textTagList.add("contentAbstract");

                //获取初始流程
                List<SmsWorkGroupApplicationProcess> processList = smsWorkGroupApplicationProcessMapper.selectList(new QueryWrapper<SmsWorkGroupApplicationProcess>()
                        .lambda()
                        .orderByAsc(SmsWorkGroupApplicationProcess::getProcessSort));
                if (processList == null || processList.size() < 1) {
                    return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
                }

                //获取申请流程
                List<SmsWorkGroupApplicationDetail> detailList = smsWorkGroupApplicationDetailMapper.selectList(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                        .lambda()
                        .eq(SmsWorkGroupApplicationDetail::getApplicationId, apply_id));
                for (SmsWorkGroupApplicationProcess process : processList) {
                    List<SmsWorkGroupApplicationDetail> filterDetail = detailList
                            .stream()
                            .filter(detail -> detail.getProcessId().equals(process.getId()))
                            .collect(Collectors.toList());
                    if (filterDetail.size() > 0) {
                        SmsWorkGroupApplicationDetail detail = filterDetail.get(0);
                        if (detail.getDetailAllowStatus() == EXAMINE_STATUS_PASS || detail.getDetailAllowStatus() == EXAMINE_STATUS_FORCED_FINISH) {
                            map.put("allowStatus" + process.getProcessSort() + "", "同意");
                        } else if (detail.getDetailAllowStatus() == WORK_STATUS_DENY || detail.getDetailAllowStatus() == WORK_STATUS_FORCED_REJECT) {
                            map.put("allowStatus" + process.getProcessSort() + "", "拒绝");
                        } else {
                            map.put("allowStatus" + process.getProcessSort() + "", "");
                        }

                        map.put("allowOption" + process.getProcessSort() + "", detail.getDetailAllowOption());

                        //添加签名
                        if (isNullOrEmpty(detail.getDetailAllowSign())) {
                            map.put("allowSign" + process.getProcessSort() + "", "");
                        } else {
                            String[] splitStr = detail.getDetailAllowSign().split("=");
                            String fileName = splitStr[splitStr.length - 1];

                            File file = new File(filePath + fileName);
                            if (file.exists()) {
                                InputStream inputStream = new FileInputStream(file);
                                PictureRenderData pictures = Pictures.ofStream(inputStream,
                                        PictureType.PNG).size(60, 60).create();

                                map.put("allowSign" + process.getProcessSort() + "", pictures);
                                picTagList.add("allowSign" + process.getProcessSort());
                            }
                        }

                        //添加印章
                        if (isNullOrEmpty(detail.getDetailAllowStamp())) {
                            map.put("allowStamp" + process.getProcessSort() + "", "");
                        } else {
                            String[] splitStr = detail.getDetailAllowStamp().split("=");
                            String fileName = splitStr[splitStr.length - 1];

                            File file = new File(filePath + fileName);
                            if (file.exists()) {
                                InputStream inputStream = new FileInputStream(file);
                                PictureRenderData pictures = Pictures.ofStream(inputStream,
                                        PictureType.PNG).size(60, 60).create();

                                map.put("allowStamp" + process.getProcessSort() + "", pictures);
                                picTagList.add("allowStamp" + process.getProcessSort());
                            }

                        }

                        //审批时间
                        if (isNullOrEmpty(detail.getDetailAllowTime())) {
                            map.put("detailAllowTime" + process.getProcessSort() + "", "");
                        } else {
                            map.put("detailAllowTime" + process.getProcessSort() + "", TimeUtil.DateHanZiSimpleFormat(detail.getDetailAllowTime()));
                        }
                    } else {
                        map.put("allowStatus" + process.getProcessSort() + "", "");
                        map.put("allowOption" + process.getProcessSort() + "", "");
                        map.put("allowSign" + process.getProcessSort() + "", "");
                        map.put("allowStamp" + process.getProcessSort() + "", "");
                        map.put("detailAllowTime" + process.getProcessSort() + "", "");
                    }
                }


                ClassPathResource resource = new ClassPathResource("applyTemplates/workApplicationGroup.docx");
                InputStream is = resource.getInputStream();
                FileOutputStream outputStream = new FileOutputStream(newFilePath);

                XWPFTemplate template = XWPFTemplate.compile(is);

                //配置图片标签
                Configure config = template.getConfig();
                for (String tag : picTagList
                ) {
                    config.customPolicy(tag, new PictureRenderPolicy());
                }
                //文字标签配置
                for (String textTag: textTagList) {
                    String tagContent = (String) map.get(textTag);
                    if (tagContent != null && tagContent.length() > 30){
                        Style style = new Style();
                        style.setFontSize(6.0);

                        TextRenderData data = new TextRenderData(tagContent,style);
                        map.put(textTag,data);
                    }
                }
                template.render(map);

                template.write(outputStream);

                is.close();
                outputStream.close();
                template.close();

                //word转pdf
                File destOri = new File(newFilePath);
                FileInputStream fileInputStream = new FileInputStream(destOri);
                FileOutputStream fileOutputStream = new FileOutputStream(pdfFilePath);

                Document document = new Document();
                document.loadFromStream(fileInputStream, FileFormat.Docx);
                //保存为PDF
                document.saveToFile(pdfFilePath, FileFormat.PDF);


                fileInputStream.close();
                fileOutputStream.close();
                document.close();

                log.debug("文件生成完成!");
            } catch (Exception e) {
                e.printStackTrace();
                return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
            }
    //    }
        try {
            // 加载PDF文档
            PDDocument doc = PDDocument.load(pdfFile);
            doc.setAllSecurityToBeRemoved(true);
            // 创建水印
            String watermark = "四川东方教育集团";
            PDPageContentStream contentStream;

            for (PDPage page : doc.getPages()) {
                contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);

                //加载字体
                ClassPathResource resource = new ClassPathResource("fonts/123.ttf");
                InputStream is = resource.getInputStream();
                PDFont font = PDType0Font.load(doc, is);


                int startX = 0; // 起始位置 x 坐标
                int startY = 0; // 起始位置 y 坐标
                float angle = -45; // 角度
                float interval = 250; // 间隔
                float opacity = 0.3f; // 透明度
                int colorR = 127; // 颜色 red 值
                int colorG = 127; // 颜色 green 值
                int colorB = 127; // 颜色 blue 值

                //透明的
                PDExtendedGraphicsState r0 = new PDExtendedGraphicsState();
                r0.setNonStrokingAlphaConstant(opacity);
                r0.setAlphaSourceFlag(true);
                contentStream.setGraphicsStateParameters(r0);

                //水印颜色
                contentStream.setNonStrokingColor(colorR, colorG, colorB);
                contentStream.beginText();
                contentStream.setFont(font, 30f);

                int x_times = (int) Math.ceil(page.getMediaBox().getWidth() / interval);
                int y_times = (int) Math.ceil(page.getMediaBox().getHeight() / interval);
                for (int x = startX; x <= x_times; x++) {
                    for (int y = startY; y <= y_times; y++) {
                        contentStream.setTextRotation(angle, (x * interval), (y * interval));
                        contentStream.showText(watermark);
                    }
                }
                contentStream.endText();
                contentStream.restoreGraphicsState();
                contentStream.close();
                is.close();
            }

//            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/vnd.pdf;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("集团工作请示单预览.pdf", "utf-8"));
            response.setHeader("file-name", URLEncoder.encode("集团工作请示单预览.pdf", "utf-8"));
            response.setHeader("file-type","download");
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
            //刷新缓冲
            response.flushBuffer();

            // 保存PDF文档
            doc.save(response.getOutputStream());
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));

        }
        return null;

    }

    @Override
    public ResponseResult selectAllApply(String apply_unit, Integer pageSize, Integer pageNum, Integer status) {
        LambdaQueryWrapper<SmsWorkGroupApplication> queryWrapper = new LambdaQueryWrapper<SmsWorkGroupApplication>().orderByDesc(SmsWorkGroupApplication::getCreateTime);
        if (!isNullOrEmpty(apply_unit)) {
            queryWrapper.like(SmsWorkGroupApplication::getRequestingUnit, apply_unit);
        }
        if (!isNullOrEmpty(status)) {
            queryWrapper.eq(SmsWorkGroupApplication::getAllowStatus,status);
        }
        Page<SmsWorkGroupApplication> page = new Page<>(pageNum, pageSize);

        smsWorkGroupApplicationMapper.selectPage(page, queryWrapper);

        List<SmsWorkGroupApplicationDTO> collect = page.getRecords().stream().map(appApplication -> {
            SmsWorkGroupApplicationDTO appApplicationResp = new SmsWorkGroupApplicationDTO();
            BeanUtils.copyProperties(appApplication, appApplicationResp);
            SmsUser smsUser = cacheUtil.getUserInfo(appApplicationResp.getApplicationApplyUserId());
            if (smsUser != null) {
                SmsWorkGroupApplicationUserDTO user = new SmsWorkGroupApplicationUserDTO();
                BeanUtils.copyProperties(smsUser, user);
                appApplicationResp.setApplyUserInfo(user);
            }

            return appApplicationResp;
        }).collect(Collectors.toList());

        int total = (int) page.getTotal();
        return CommonResult.success(collect, total);
    }

    @Override
    @Async
    public Future<ResponseResult> exportWorkGroupApplication(SmsWorkGroupApplicationExportVO smsWorkGroupApplicationExportVO, HttpServletResponse response) {
        if (isNullOrEmpty(smsWorkGroupApplicationExportVO.getIsExportProcess())) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }
        try {
            QueryWrapper<SmsWorkGroupApplication> queryWrapper = new QueryWrapper<>();

            if (!isNullOrEmpty(smsWorkGroupApplicationExportVO.getRequestingUnit())) {
                queryWrapper.lambda().like(SmsWorkGroupApplication::getRequestingUnit, smsWorkGroupApplicationExportVO.getRequestingUnit());
            }

            queryWrapper.lambda().orderByDesc(SmsWorkGroupApplication::getCreateTime);
            List<SmsWorkGroupApplication> list = smsWorkGroupApplicationMapper.selectList(queryWrapper);
            //表头数据
            String[] header = smsWorkGroupApplicationExportVO.getLimitColumn().toArray(new String[0]);
            double sheetNum;
            //声明一个工作簿
            HSSFWorkbook workbook = new HSSFWorkbook();
            if (list != null && list.size() > 0) {
                sheetNum = Math.ceil((double) list.size() / PER_SHEET_NUM);
                for (int k = 0; k < sheetNum; k++) {
                    //生成一个表格，设置表格名称为"资源导出表"
                    HSSFSheet sheet = workbook.createSheet("集团工作请示记录导出表" + (k + 1));

                    //设置表格列宽度为10个字节
                    sheet.setDefaultColumnWidth(12);
                    //创建标题的显示样式
                    HSSFCellStyle headerStyle = workbook.createCellStyle();
                    headerStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
                    headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                    HSSFFont f = workbook.createFont();
                    f.setFontHeightInPoints((short) 10);//字号
                    f.setBold(true);//加粗
                    headerStyle.setFont(f);
                    //创建第一行表头
                    HSSFRow headrow = sheet.createRow(0);

                    //遍历添加表头(下面模拟遍历学生，也是同样的操作过程)
                    for (int i = 0; i < header.length + 1; i++) {
                        //创建一个单元格
                        HSSFCell cell = headrow.createCell(i);

                        if (i == 0) {
                            //创建一个内容对象
                            HSSFRichTextString text = new HSSFRichTextString("序号");
                            //将内容对象的文字内容写入到单元格中
                            cell.setCellValue(text);
                            cell.setCellStyle(headerStyle);
                            continue;
                        }
                        //创建一个内容对象
                        String header1 = apiModelUtil.getFieldValueByFieldName(SmsWorkGroupApplication.class, header[i - 1]);
                        HSSFRichTextString text = new HSSFRichTextString(header1);

                        //将内容对象的文字内容写入到单元格中
                        cell.setCellValue(text);
                        cell.setCellStyle(headerStyle);
                    }

                    //判断是否需要添加流程表头
                    if (smsWorkGroupApplicationExportVO.getIsExportProcess() == EXPORT_PROCESS_TRUE) {
                        List<SmsWorkGroupApplicationProcess> processList =
                                smsWorkGroupApplicationProcessMapper.selectList(new QueryWrapper<>());
                        if (processList != null && processList.size() > 0) {
                            Integer origin_num = header.length + 1;
                            for (SmsWorkGroupApplicationProcess process : processList) {
                                String process_name = process.getProcessName();
                                addProcessTableHead(headrow, headerStyle, origin_num, process_name);
                                origin_num += 4;
                            }
                        }
                    }

                    int range = PER_SHEET_NUM;
                    if (k + 1 == sheetNum) {
                        range = list.size() - (PER_SHEET_NUM) * k;
                    }
                    for (int i = 0; i < range; i++) {
                        //创建一行
                        HSSFRow row1 = sheet.createRow(i + 1);
                        SmsWorkGroupApplication smsWorkGroupApplication = list.get((PER_SHEET_NUM) * k + i);
                        Map map = JSONObject.parseObject(JSON.toJSONString(smsWorkGroupApplication), Map.class);
                        row1.createCell(0).setCellValue(new HSSFRichTextString(i + 1 + ""));
                        for (int j = 0; j < header.length; j++) {
                            String rowContent = "";
                            if (map.get(header[j]) instanceof Long) {
                                rowContent = TimeUtil.DateformatTimestamp((long) map.get(header[j]));
                            } else {
                                if (header[j].equals("applicationApplyUserId")) {
                                    SmsUser smsUser = cacheUtil.getUserInfo(smsWorkGroupApplication.getApplicationApplyUserId());
                                    if (smsUser != null) {
                                        rowContent = smsUser.getRealName();
                                    } else {
                                        rowContent = "";
                                    }
                                } else if (header[j].equals("upLoadAnnex")) {
                                    rowContent = "";
                                } else {
                                    rowContent = (String) map.get(header[j]);
                                }
                            }
                            row1.createCell(j + 1).setCellValue(new HSSFRichTextString(rowContent));
                        }

                        if (smsWorkGroupApplicationExportVO.getIsExportProcess() == EXPORT_PROCESS_TRUE) {
                            List<SmsWorkGroupApplicationProcess> processList =
                                    smsWorkGroupApplicationProcessMapper.selectList(new QueryWrapper<>());
                            if (processList != null && processList.size() > 0) {
                                Integer origin_num = header.length + 1;
                                for (SmsWorkGroupApplicationProcess process : processList) {
                                    SmsWorkGroupApplicationDetail detail =
                                            smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                                                    .lambda()
                                                    .eq(SmsWorkGroupApplicationDetail::getApplicationId, smsWorkGroupApplication.getId())
                                                    .eq(SmsWorkGroupApplicationDetail::getProcessId, process.getId()));
                                    if (detail == null || detail.getId() == null) {
                                        origin_num += 4;
                                    } else {
                                        //审批人
                                        SmsUser user = cacheUtil.getUserInfo(detail.getDetailAllowUserId());
                                        if (user == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(user.getRealName()));
                                        }

                                        //审批时间
                                        Date allow_time = detail.getDetailAllowTime();
                                        if (allow_time == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(TimeUtil.DateHanZiSimpleFormat(allow_time)));
                                        }

                                        //审批状态
                                        Integer allow_status = detail.getDetailAllowStatus();
                                        if (allow_status == EXAMINE_STATUS_PASS || allow_status == EXAMINE_STATUS_FORCED_FINISH) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("同意"));
                                        } else if (allow_status == EXAMINE_STATUS_DENY || allow_status == EXAMINE_STATUS_FORCED_REJECT) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("拒绝"));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        }

                                        //审批意见
                                        String allow_option = detail.getDetailAllowOption();
                                        if (isNullOrEmpty(allow_option)) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(allow_option));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

//            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("集团工作请示记录导出表.xlsx", "utf-8"));
            response.setCharacterEncoding("utf-8");
            response.setHeader("file-type", "download");
            response.setHeader("file-name", URLEncoder.encode("集团工作请示记录导出表.xlsx", "utf-8"));
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
//            //刷新缓冲
            response.flushBuffer();
            //workbook将Excel写入到response的输出流中，供页面下载
            OutputStream os = response.getOutputStream();
            workbook.write(os);

            workbook.close();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        return null;
    }



    private void addProcessTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer origin_cell_num, String originHeadContent) {
        Integer cell_num = origin_cell_num;

        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批人");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批时间");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批状态");
        setTableHead(headRow, headerStyle, cell_num, originHeadContent + "审批意见");

    }
    private void setTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer cell_num, String headContent) {
        HSSFCell cell = headRow.createCell(cell_num);
        //创建一个内容对象
        HSSFRichTextString text = new HSSFRichTextString(headContent);

        //将内容对象的文字内容写入到单元格中
        cell.setCellValue(text);
        cell.setCellStyle(headerStyle);
    }

    @Override
    @Transactional
    public ResponseResult forcedFinishWorkGroupApplication(String applyId, String userId) {
        //校验数据
        if (isNullOrEmpty(applyId)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsWorkGroupApplication smsWorkGroupApplication = smsWorkGroupApplicationMapper.selectById(applyId);
        if(isNullOrEmpty(smsWorkGroupApplication)){
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_EXIST);
        }

        if(smsWorkGroupApplication.getAllowStatus() != WORK_STATUS_WAIT_ALLOW){
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_FORCED);
        }

        //修改审批表状态为通过
        smsWorkGroupApplication.setAllowStatus(WORK_STATUS_PASS);
        smsWorkGroupApplication.setEndTime(new Date());
        smsWorkGroupApplicationMapper.updateById(smsWorkGroupApplication);

        //修改节点为强制归档
        SmsWorkGroupApplicationDetail smsWorkGroupApplicationDetail = new SmsWorkGroupApplicationDetail();
        smsWorkGroupApplicationDetail.setDetailAllowStatus(WORK_STATUS_FORCED_FINISH);
        smsWorkGroupApplicationDetail.setDetailAllowUserId(userId);
        smsWorkGroupApplicationDetail.setDetailAllowTime(new Date());
        smsWorkGroupApplicationDetailMapper.update(smsWorkGroupApplicationDetail,new LambdaQueryWrapper<SmsWorkGroupApplicationDetail>()
        .eq(SmsWorkGroupApplicationDetail::getApplicationId,applyId)
        .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus,WORK_STATUS_WAIT_ALLOW));

        //消息通知
        newTipsUtil.cancelFinishTips(applyId);

        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult forcedTorsionWorkGroupApplication(SmsWorkApplicationDetailTorsionVO torsionVO) {
        if(isNullOrEmpty(torsionVO.getDetailId(),torsionVO.getApplyId(),torsionVO.getProcessObjectType(),torsionVO.getProcessObjectId())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验申请表和节点表
        SmsWorkGroupApplication smsWorkGroupApplication = smsWorkGroupApplicationMapper.selectById(torsionVO.getApplyId());
        if(isNullOrEmpty(smsWorkGroupApplication)){
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_EXIST);
        }
        SmsWorkGroupApplicationDetail detail = smsWorkGroupApplicationDetailMapper.selectById(torsionVO.getDetailId());
        if(isNullOrEmpty(detail)){
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_DETAIL_NOT_FORCED);
        }
        if(detail.getDetailAllowStatus() != WORK_STATUS_WAIT_ALLOW){
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_TORSION);
        }
        detail.setProcessObjectType(torsionVO.getProcessObjectType());
        detail.setProcessObjectId(torsionVO.getProcessObjectId());
        smsWorkGroupApplicationDetailMapper.updateById(detail);
        //消息通知
        //判断第一节点直接发消息,其他要前节点审批后才发该节点通知
        boolean flag = true;
        if(!detail.getDetailSort().equals(1)){
            SmsWorkGroupApplicationDetail beforeDetail = smsWorkGroupApplicationDetailMapper.selectOne(new LambdaQueryWrapper<SmsWorkGroupApplicationDetail>()
                    .eq(SmsWorkGroupApplicationDetail::getApplicationId, torsionVO.getApplyId())
                    .eq(SmsWorkGroupApplicationDetail::getDetailSort, detail.getDetailSort() - 1));
            if(beforeDetail.getDetailAllowStatus() != EXAMINE_STATUS_PASS){
              flag = false;
            }
        }
        if(flag) {
            RangeTypeEnum rangeTypeEnum;
            if (detail.getProcessObjectType() == AGREEMENT_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeList = new ArrayList<>();
            rangeList.add(detail.getProcessObjectId());
            newTipsUtil.allowContinueTips(torsionVO.getApplyId(),
                    null,
                    rangeTypeEnum,
                    rangeList,
                    detail.getId());
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult replaceApplyWorkGroupApplication(String userId, SmsWorkGroupApplicationAllowVO allowVO) {
        if (isNullOrEmpty(allowVO.getApplication_id()) || isNullOrEmpty(allowVO.getDetail_id())
                || isNullOrEmpty(allowVO.getDetailAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (allowVO.getDetailAllowStatus() != WORK_STATUS_PASS
                && allowVO.getDetailAllowStatus() != WORK_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWorkGroupApplicationDetail applicationDetail =
                smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                        .lambda()
                        .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id())
                        .eq(SmsWorkGroupApplicationDetail::getId, allowVO.getDetail_id())
                        .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_WAIT_ALLOW));
        if (isNullOrEmpty(applicationDetail)) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_ALLOW_FAIL);
        }

        if (!applicationDetail.getDetailSort().equals(1)) {
            SmsWorkGroupApplicationDetail preDetail =
                    smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                            .lambda()
                            .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id())
                            .eq(SmsWorkGroupApplicationDetail::getDetailSort, applicationDetail.getDetailSort() - 1));
            if (preDetail != null && !isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getDetailAllowStatus() != WORK_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_ALLOW_FAIL);
                }
            }
        }


        SmsWorkGroupApplicationDetail allowDetail = new SmsWorkGroupApplicationDetail();
        allowDetail.setId(allowVO.getDetail_id());
        allowDetail.setDetailAllowStatus(allowVO.getDetailAllowStatus());
        if (!isNullOrEmpty(allowVO.getDetailAllowOpinion())) {
            allowDetail.setDetailAllowOption(allowVO.getDetailAllowOpinion());
        }
        Date nowDate = new Date();
        allowDetail.setDetailAllowTime(nowDate);
        allowDetail.setDetailAllowUserId(userId);
        allowDetail.setDetailAllowSign(allowVO.getDetailAllowSign());
        allowDetail.setDetailAllowStamp(allowVO.getDetailAllowStamp());

        smsWorkGroupApplicationDetailMapper.updateById(allowDetail);

        boolean is_done = false;

        //判断是否最后一个节点 是否驳回
        Integer detailCount = smsWorkGroupApplicationDetailMapper.selectCount(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                .lambda()
                .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id()));
        if (detailCount.equals(applicationDetail.getDetailSort()) || allowVO.getDetailAllowStatus() == WORK_STATUS_DENY) {
            is_done = true;

            SmsWorkGroupApplication updateApplication = new SmsWorkGroupApplication();
            updateApplication.setId(allowVO.getApplication_id());
            updateApplication.setEndTime(nowDate);
            updateApplication.setAllowStatus(allowVO.getDetailAllowStatus());
            smsWorkGroupApplicationMapper.updateById(updateApplication);
        }

        //节点驳回 重置其余节点状态
        if (allowVO.getDetailAllowStatus() == WORK_STATUS_DENY) {
            SmsWorkGroupApplicationDetail updateDenyDetail =
                    new SmsWorkGroupApplicationDetail();
            updateDenyDetail.setDetailAllowStatus(WORK_STATUS_DENY_FINISH);
            smsWorkGroupApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsWorkGroupApplicationDetail>()
                    .lambda()
                    .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id())
                    .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_WAIT_ALLOW));
        }


        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (allowVO.getDetailAllowStatus() == WORK_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(allowVO.getApplication_id(), userId, result_status);
        } else {
            SmsWorkGroupApplicationDetail nextDetail =
                    smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                            .lambda()
                            .eq(SmsWorkGroupApplicationDetail::getApplicationId, allowVO.getApplication_id())
                            .eq(SmsWorkGroupApplicationDetail::getDetailSort, applicationDetail.getDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum;
            if (nextDetail.getProcessIsApplicationEdit().equals(1)) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                if (nextDetail.getProcessObjectType() == WORK_APPLICATION_OBJECT_TYPE_ROLE) {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
                } else {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                }
            }

            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(allowVO.getApplication_id(),
                    null,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult forcedRejectWorkGroupApplication(SmsWorkGroupApplicationForceVO forceVO, String userId) {
        if (isNullOrEmpty(forceVO.getApplyId(),forceVO.getDetailAllowOption())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验
        SmsWorkGroupApplication smsWorkGroupApplication = smsWorkGroupApplicationMapper.selectById(forceVO.getApplyId());
        if (isNullOrEmpty(smsWorkGroupApplication)) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_EXIST);
        }
        //总状态只有为待审批才能强制驳回
        Integer allowStatus = smsWorkGroupApplication.getAllowStatus();
        if (allowStatus != WORK_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_FORCED_REJECT);
        }
        //修改申请表状态为驳回
        smsWorkGroupApplication.setAllowStatus(WORK_STATUS_DENY);
        smsWorkGroupApplication.setEndTime(new Date());
        smsWorkGroupApplicationMapper.updateById(smsWorkGroupApplication);
        //修改节点状态为强制驳回
        SmsWorkGroupApplicationDetail smsWorkGroupApplicationDetail = new SmsWorkGroupApplicationDetail();
        smsWorkGroupApplicationDetail.setDetailAllowTime(new Date());
        smsWorkGroupApplicationDetail.setDetailAllowUserId(userId);
        smsWorkGroupApplicationDetail.setDetailAllowStatus(WORK_STATUS_FORCED_REJECT);
        smsWorkGroupApplicationDetail.setDetailAllowOption(forceVO.getDetailAllowOption());
        smsWorkGroupApplicationDetailMapper.update(smsWorkGroupApplicationDetail, new LambdaQueryWrapper<SmsWorkGroupApplicationDetail>()
                .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_WAIT_ALLOW)
                .eq(SmsWorkGroupApplicationDetail::getApplicationId, forceVO.getApplyId()));
        //消息提醒
        newTipsUtil.cancelFinishTips(forceVO.getApplyId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult deletedWorkGroupApplication(String applyId) {
        SmsWorkGroupApplication smsWorkGroupApplication = smsWorkGroupApplicationMapper.selectById(applyId);
        if (isNullOrEmpty(smsWorkGroupApplication)) {
            return CommonResult.failed(CommonCodeEnum.APPLICATION_NOT_EXIST);
        }

        //删除消息
        List<SmsNewTips> smsNewTipList = smsNewTipsMapper.selectList(new LambdaQueryWrapper<SmsNewTips>().eq(SmsNewTips::getEventId, applyId));
        if (!smsNewTipList.isEmpty()) {
            List<String> newTipsIdList = smsNewTipList.stream().map(SmsNewTips::getId).collect(Collectors.toList());
            smsNewTipsMapper.deleteBatchIds(newTipsIdList);
            smsNewTipsRecordMapper.delete(new LambdaQueryWrapper<SmsNewTipsRecord>().in(SmsNewTipsRecord::getRecordTipsId, newTipsIdList));
        }
        //删除申请表
        smsWorkGroupApplicationMapper.deleteById(applyId);

        //删除节点
        smsWorkGroupApplicationDetailMapper.delete(new LambdaQueryWrapper<SmsWorkGroupApplicationDetail>().eq(SmsWorkGroupApplicationDetail::getApplicationId, applyId));

        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult updateOpinion(SmsWorkGroupApplicationUpdateOpinionVo updateOpinionVo, String userId) {
        if (isNullOrEmpty(updateOpinionVo.getApplyId()) || isNullOrEmpty(updateOpinionVo.getDetailId())
                || isNullOrEmpty(updateOpinionVo.getDetailAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //查申请表是否存在
        SmsWorkGroupApplication smsWorkGroupApplication = smsWorkGroupApplicationMapper.selectById(updateOpinionVo.getApplyId());
        if (isNullOrEmpty(smsWorkGroupApplication)) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_EXIST);
        }
        //校验该节点是否存在,申请人是否是自己
        SmsWorkGroupApplicationDetail applicationDetail =
                smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                        .lambda()
                        .eq(SmsWorkGroupApplicationDetail::getApplicationId, updateOpinionVo.getApplyId())
                        .eq(SmsWorkGroupApplicationDetail::getId, updateOpinionVo.getDetailId())
                        .eq(SmsWorkGroupApplicationDetail::getDetailAllowUserId, userId));
        if (isNullOrEmpty(applicationDetail)) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_PROCESS_NOT_EXIST);
        }
        //节点状态为拒绝 不可修改
        if (updateOpinionVo.getDetailAllowStatus() != WORK_STATUS_PASS
                && updateOpinionVo.getDetailAllowStatus() != WORK_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }


        //校验不是最后个节点时,下一个节点未审批才能修改意见
        Integer detailSort = applicationDetail.getDetailSort();
        Integer count = smsWorkGroupApplicationDetailMapper.selectCount(new LambdaQueryWrapper<>());
        if (!detailSort.equals(count)){
            SmsWorkGroupApplicationDetail nextDetail = smsWorkGroupApplicationDetailMapper.selectOne(new QueryWrapper<SmsWorkGroupApplicationDetail>()
                    .lambda()
                    .eq(SmsWorkGroupApplicationDetail::getApplicationId, updateOpinionVo.getApplyId())
                    .eq(SmsWorkGroupApplicationDetail::getDetailSort, detailSort + 1));
            if (isNullOrEmpty(nextDetail)) {
                return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_UPDATE_OPINION_FAIL);
            }
            Integer detailAllowStatus = nextDetail.getDetailAllowStatus();
            if (isNullOrEmpty(detailAllowStatus)){
                return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_UPDATE_OPINION_FAIL);
            }
        }
        applicationDetail.setDetailAllowStatus(updateOpinionVo.getDetailAllowStatus());
        if (!isNullOrEmpty(updateOpinionVo.getDetailAllowOpinion())) {
            applicationDetail.setDetailAllowOption(updateOpinionVo.getDetailAllowOpinion());
        }
        Date nowDate = new Date();
        applicationDetail.setDetailAllowTime(nowDate);

        if (applicationDetail.getProcessIsSign()) {
            if (isNullOrEmpty(updateOpinionVo.getDetailAllowSign())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            applicationDetail.setDetailAllowSign(updateOpinionVo.getDetailAllowSign());
        }
        if (applicationDetail.getProcessIsStamp()) {
            if (isNullOrEmpty(updateOpinionVo.getDetailAllowStamp())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            applicationDetail.setDetailAllowStamp(updateOpinionVo.getDetailAllowStamp());
        }
        smsWorkGroupApplicationDetailMapper.updateById(applicationDetail);
        //申请表修改状态
        String applicationId = smsWorkGroupApplication.getId();

        boolean is_done = false;
        if (count.equals(applicationDetail.getDetailSort()) || updateOpinionVo.getDetailAllowStatus() == WORK_STATUS_DENY) {
            is_done = true;

            SmsWorkGroupApplication updateApplication = new SmsWorkGroupApplication();
            updateApplication.setId(updateOpinionVo.getApplyId());
            updateApplication.setEndTime(nowDate);
            updateApplication.setAllowStatus(updateOpinionVo.getDetailAllowStatus());
            smsWorkGroupApplicationMapper.updateById(updateApplication);
        }

        //节点驳回 重置其余节点状态
        SmsWorkGroupApplicationDetail updateDenyDetail =
                new SmsWorkGroupApplicationDetail();
        if (updateOpinionVo.getDetailAllowStatus() == WORK_STATUS_DENY) {

            updateDenyDetail.setDetailAllowStatus(WORK_STATUS_DENY_FINISH);
            smsWorkGroupApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsWorkGroupApplicationDetail>()
                    .lambda()
                    .eq(SmsWorkGroupApplicationDetail::getApplicationId, updateOpinionVo.getApplyId())
                    .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_WAIT_ALLOW));
        }else{
            updateDenyDetail.setDetailAllowStatus(WORK_STATUS_WAIT_ALLOW);
            smsWorkGroupApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsWorkGroupApplicationDetail>()
                    .lambda()
                    .eq(SmsWorkGroupApplicationDetail::getApplicationId, updateOpinionVo.getApplyId())
                    .eq(SmsWorkGroupApplicationDetail::getDetailAllowStatus, WORK_STATUS_DENY_FINISH));
        }


        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (updateOpinionVo.getDetailAllowStatus() == WORK_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(updateOpinionVo.getApplyId(), userId, result_status);
        } else {
            //之前该节点驳回了,消息重新发起
            if (smsWorkGroupApplication.getAllowStatus() == WORK_STATUS_DENY && updateOpinionVo.getDetailAllowStatus() == WORK_STATUS_PASS) {
                //查找消息标题
                String tipsContent = null;
                List<SmsNewTips> newTipsList = smsNewTipsMapper.selectList(new LambdaQueryWrapper<SmsNewTips>()
                        .eq(SmsNewTips::getEventId, updateOpinionVo.getApplyId())
                        .eq(SmsNewTips::getTipsType, TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW.getValue())
                        .orderByDesc(SmsNewTips::getCreateTime));
                if (!newTipsList.isEmpty()) {
                    tipsContent = newTipsList.get(0).getTipsContent();
                }
                smsWorkGroupApplication.setAllowStatus(WORK_STATUS_PASS);
                smsWorkGroupApplicationMapper.updateById(smsWorkGroupApplication);

                RangeTypeEnum rangeTypeEnum;
                if (applicationDetail.getProcessObjectType() == WORK_APPLICATION_OBJECT_TYPE_PERSON) {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                } else {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
                }
                List<String> rangeList = new ArrayList<>();
                rangeList.add(applicationDetail.getProcessObjectId());
                newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                        userId,
                        rangeTypeEnum,
                        rangeList,
                        COPY_TYPE_ENUM_NONE,
                        null,
                        AppTypeEnum.APP_TYPE_ENUM_WORK_GROUP_APPLICATION,
                        applicationId,
                        null,
                        null,
                        applicationDetail.getId(),
                        null,
                        null,
                        null,
                        tipsContent);

            }
        }

        return CommonResult.success();
    }

    @Override
    public ResponseResult updateAnnex(SmsWorkGroupApplicationUpdateAnnexVo updateAnnexVo, String userId) {
        if (isNullOrEmpty(updateAnnexVo.getApplyId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //查申请表是否存在
        SmsWorkGroupApplication smsWorkGroupApplication = smsWorkGroupApplicationMapper.selectById(updateAnnexVo.getApplyId());
        if (isNullOrEmpty(smsWorkGroupApplication)) {
            return CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_NOT_EXIST);
        }
        //校验是否是本人
        smsWorkGroupApplication.setIsAnnex(updateAnnexVo.getIsAnnex());
        smsWorkGroupApplication.setUpLoadAnnex(updateAnnexVo.getUpLoadAnnex());
        smsWorkGroupApplicationMapper.updateById(smsWorkGroupApplication);
        return CommonResult.success();
    }
}
